#coding: utf-8
#-------------------------------------------------------------------------------
# Name:        Main
# Purpose:     Controla o fluxo principal do programa
#
# Author:      Johann
#
# Created:     23/11/2010
# Copyright:   (c) Johann 2010
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python

from Tempo import Tempo
from Transito import Transito
from Lembrete import Lembrete
from Conta import Conta
from RepositorioContas import RepositorioContas
from InformacoesDoSistema import InformacoesDoSistema

from InterfacePygame import InterfacePygame
from InterfaceTkinter import InterfaceTkinter

# getcwd, listdir e remove são usados para visualização de diretórios
from os import getcwd, listdir, remove

from datetime import datetime

# as funções abaixo são usadas para o envio de emails
from smtplib import SMTP
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders

# codecs é uma biblioteca usada para manipulação de arquivos com conteúdo unicode
import codecs

class Main:
    """Controla o fluxo principal do programa"""

    def __init__(self):
        self.repositoriocontas = RepositorioContas()
        self.interfacepygame = InterfacePygame()
        self.interfacetkinter = InterfaceTkinter()
        self.informacoessistema = InformacoesDoSistema("PyMemo", "alpha 1.0", "Fabiana Almeida, Fernanda Araújo, Johann Gomes, Thaís Freitas", "http://pythonmemo.googlecode.com")

        # as contas são carregadas direto dos arquivos salvos
        try:
            self.carregarContas()
        except:
            pass
##        for conta in self.repositoriocontas.listacontas:
##            print conta.getUsuario()
        try:
            self.carregarLembretes()
        except:
            pass
##        for conta in self.repositoriocontas.listacontas:
##            print "lista de", conta.getUsuario(), conta.listalembretes
##            for lembrete in conta.listalembretes:
##                print lembrete.getTexto(), lembrete.getHora(), lembrete.getData()

    def salvarContas(self):
        """Salva contas em arquivo para posterior carregamento"""

        for conta in self.repositoriocontas.listacontas:
            file = codecs.open("arquivos\\contas\\" + conta.getUsuario() + ".txt", "w+", "utf-8")
            file.write(conta.getUsuario() + "\r\n" + conta.getSenha() + "\r\n" + conta.getEmail() + "\r\n" + conta.getCidade() + "\r\n\r\n")
            file.close()

    def carregarContas(self):
        """Carrega contas salvas em arquivo"""

        diretorio = listdir("arquivos\\contas")
        for arquivo in diretorio:
            if ".txt" in arquivo:
                file = codecs.open("arquivos\\contas\\" + arquivo, "r+", "utf-8")
                conteudo = file.readlines()
                self.repositoriocontas.adicionarConta(Conta(conteudo[0].strip(), conteudo[1].strip(), conteudo[2].strip(), conteudo[3].strip()))

    def salvarLembretes(self):
        """Salva lembretes em arquivo para posterior carregamento"""

        for conta in self.repositoriocontas.listacontas:
            file = codecs.open("arquivos\\lembretes\\" + conta.getUsuario() + ".txt", "w+", "utf-8")
            for lembrete in conta.listalembretes:
                file.write(lembrete.getTexto() + "\r\n" + lembrete.getHora() + "\r\n" + lembrete.getData() + "\r\n\r\n")
            file.close()

    def carregarLembretes(self):
        """Carrega lembretes salvos em arquivo"""

        diretorio = listdir("arquivos\\lembretes")
        for arquivo in diretorio:
            if ".txt" in arquivo:
                file = codecs.open("arquivos\\lembretes\\" + arquivo, "r+", "utf-8")
                conteudo = file.readlines()
                for conta in self.repositoriocontas.listacontas:
                    print conta.getUsuario(), arquivo[:-4]
                    if conta.getUsuario().encode('cp1252') == arquivo[:-4]:
                        print conta.getUsuario(), conta.listalembretes
                        for indicelinha in range(len(conteudo)):
                            if indicelinha % 4 == 0:
                                conta.adicionarLembrete(Lembrete(conteudo[indicelinha].strip(), conteudo[indicelinha + 1].strip(), conteudo[indicelinha + 2].strip()))
        file.close()

    def tratarAdicionarConta(self, infoconta):
        """Trata dados recebidos via Tkinter e usa-os para adicionar uma conta no repositório"""

        if infoconta != False:
            # preencheu corretamente
            self.repositoriocontas.adicionarConta(Conta(infoconta[0], infoconta[1], infoconta[2], infoconta[3].capitalize()))
            print self.repositoriocontas.listacontas
        self.salvarContas()
        self.painelContas()

    def tratarEditarConta(self, infoconta):
        """Trata dados recebidos via Tkinter e usa-os para editar uma conta do repositório"""

        # preencheu corretamente
        if infoconta != False:
            # verifica se a conta realmente existe
            if self.repositoriocontas.verificarConta(infoconta[0], infoconta[1]) == True:
                infoedicao = self.interfacetkinter.janelaEditarUsuario(infoconta[0])
                if infoedicao != False:
                    remove("arquivos\\contas\\" + infoconta[0] + ".txt")
                    self.repositoriocontas.alterarConta(self.repositoriocontas.retornarConta(infoconta[0], infoconta[1]), infoedicao[0], infoedicao[1], infoedicao[2], infoedicao[3])
                    print self.repositoriocontas.listacontas
            else:
                # se não encontrou a conta, ela não existe, avisando...
                self.interfacetkinter.janelaMensagem("Erro", "Conta inexistente, verifique se você preencheu os campos corretamente")
        self.salvarContas()
        self.painelContas()

    def tratarExcluirConta(self, infoconta):
        """Trata dados recebidos via Tkinter e usa-os para excluir uma conta do repositório"""

        # preencheu corretamente
        if infoconta != False:
            # verifica se a conta realmente existe
            if self.repositoriocontas.verificarConta(infoconta[0], infoconta[1]) == True:
                remove("arquivos\\contas\\" + infoconta[0] + ".txt")
                try:
                    remove("arquivos\\lembretes\\" + infoconta[0] + ".txt")
                except:
                    pass
                self.repositoriocontas.excluirConta(self.repositoriocontas.retornarConta(infoconta[0], infoconta[1]))
                print self.repositoriocontas.listacontas
            else:
                # se não encontrou a conta, ela não existe, avisando...
                self.interfacetkinter.janelaMensagem("Erro", "Conta inexistente, verifique se você preencheu os campos corretamente")
        self.salvarContas()
        self.painelContas()



    def painelContas(self):
        """Responsável pelas operações gerais no painel de contas de usuário"""

        opcao = self.interfacepygame.janelaContas(self.repositoriocontas.listacontas)
        print opcao
        if opcao == "adicionarconta":
            self.tratarAdicionarConta(self.interfacetkinter.janelaNovoUsuario())
        elif opcao == "editarconta":
            # primeiro busca-se o usuário para sabermos se o mesmo existe
            self.tratarEditarConta(self.interfacetkinter.janelaBuscarUsuario())
        elif opcao == "excluirconta":
            # primeiro busca-se o usuário para sabermos se o mesmo existe
            self.tratarExcluirConta(self.interfacetkinter.janelaBuscarUsuario())
        elif opcao == "sobre":
            self.interfacetkinter.janelaMensagem(self.informacoessistema.getNomeDoSistema() + " " + self.informacoessistema.getVersao(), self.informacoessistema.getCreditos() + " " + self.informacoessistema.getLinks(), "interface\\botoes\\logosobre.gif")
            self.painelContas()
        else:
            # o usuário só pode ter clicado em uma conta
            conta = opcao
            senhacapturada = self.interfacetkinter.janelaLogar(conta.getUsuario())
            # nada foi preenchido
            if senhacapturada == False:
                self.painelContas()
            else:
                # entraram com alguma coisa, vamos verificar se a senha confere com o usuário!
                if self.repositoriocontas.verificarConta(conta.getUsuario(), senhacapturada) == True:
                    self.painelLembretes(conta)
                else:
                    self.interfacetkinter.janelaMensagem("Erro!", "Senha inválida")
                    self.painelContas()

    def tratarAdicionarLembrete(self, infolembrete, conta):
        """Trata dados recebidos via Tkinter e usa-os para adicionar um lembrete a uma conta do repositório"""

        if infolembrete != False:
            texto, hora, data = infolembrete
##                print texto, hora, data
            if hora == "":
                hora = self.interfacepygame.capturarHora()
            if data == "":
                data = str(datetime.now())[8:10] + str(datetime.now())[5:7]
            print texto, hora, data
            conta.adicionarLembrete(Lembrete(texto, hora, data))
        self.salvarLembretes()
        self.painelLembretes(conta)

    def tratarExcluirLembrete(self, infolembrete, conta):
        """Trata dados recebidos via Tkinter e usa-os para excluir um lembrete de uma conta do repositório"""

        if infolembrete != False:
            hora, data = infolembrete
            if data == "":
                data = str(datetime.now())[8:10] + str(datetime.now())[5:7]
            print hora, data
            if conta.verificarLembrete(data, hora) == True:
                conta.excluirLembrete(conta.retornarLembrete(data, hora))
            else:
                self.interfacetkinter.janelaMensagem("Erro", "Lembrete não encontrado na conta de " + conta.getUsuario())
        self.salvarLembretes()
        self.painelLembretes(conta)

    def tratarVisualizarLembretes(self, conta):
        """Trata dados recebidos via Tkinter e usa-os para visualizarmos todos os lembrete de uma conta do repositório"""

        datasordenadas = []
        for lembrete in conta.listalembretes:
            if lembrete.getData() not in datasordenadas:
                datasordenadas.append(lembrete.getData())
        datasordenadas.sort()
        self.interfacetkinter.janelaVisualizarTodosLembretes(conta, datasordenadas)
        self.painelLembretes(conta)

    def tratarEditarLembrete(self, infolembrete, conta):
        """Trata dados recebidos via Tkinter e usa-os para editar um lembrete de uma conta do repositório"""

        if infolembrete != False:
            hora, data = infolembrete
            if data == "":
                data = str(datetime.now())[8:10] + str(datetime.now())[5:7]
            print hora, data
            if conta.verificarLembrete(data, hora) == True:
                conta.excluirLembrete(conta.retornarLembrete(data, hora))
                self.tratarAdicionarLembrete(self.interfacetkinter.janelaNovoLembrete(), conta)
            else:
                self.interfacetkinter.janelaMensagem("Erro", "Lembrete não encontrado na conta de " + conta.getUsuario())
        self.salvarLembretes()
        self.painelLembretes(conta)

    def painelLembretes(self, conta):
        """Responsável pelas opções gerais no painel de lembretes"""

        opcao = self.interfacepygame.janelaLembretes(conta)
        if opcao == "adicionarlembrete":
            self.tratarAdicionarLembrete(self.interfacetkinter.janelaNovoLembrete(), conta)
        elif opcao == "excluirlembrete":
            self.tratarExcluirLembrete(self.interfacetkinter.janelaBuscarLembrete(), conta)
        elif opcao == "editarlembrete":
            self.tratarEditarLembrete(self.interfacetkinter.janelaBuscarLembrete(), conta)
        elif opcao == "visualizartodoslembretes":
            self.tratarVisualizarLembretes(conta)
        elif opcao == "visualizartransito":
            cidadeencontrada = False
            for cidade in ("Recife", "Fortaleza", "Rio_de_janeiro", "Sao_paulo", "Manaus", "Para", "Goiania", "Curitiba", "Florianopolis", "Porto_alegre", "Belo_horizonte", "Espirito_santo", "Washington", "London"):
                if cidade == conta.getCidade():
                    cidadeencontrada = True
                    self.interfacetkinter.janelaVisualizarTransito(Transito().atualizarEventos(Transito().localizarTwitter(conta.getCidade())))
            if cidadeencontrada == False:
                self.interfacetkinter.janelaMensagem("Erro", "O sistema não possui informações para sua cidade")
            self.painelLembretes(conta)
        elif opcao == "enviaremail":
            try:
                self.enviarEmail(conta)
                self.interfacetkinter.janelaMensagem("Sucesso!", "E-mail enviado para " + conta.getEmail())
            except:
                self.interfacetkinter.janelaMensagem("Erro", "Não conseguimos enviar um e-mail para sua conta, verifique se ele foi registrado corretamente\ne pertence a algum dos seguintes servidores:\nUOL, Terra, IG, iBest, iTelefônica, Gmail, Yahoo, Hotmail ou BOL")
            self.painelLembretes(conta)
        elif opcao == "sobre":
            self.interfacetkinter.janelaMensagem(self.informacoessistema.getNomeDoSistema() + " " + self.informacoessistema.getVersao(), self.informacoessistema.getCreditos() + " " + self.informacoessistema.getLinks(), "interface\\botoes\\logosobre.gif")
            self.painelLembretes(conta)
        elif opcao == "logoff":
            self.painelContas()

    def enviarEmail(self, conta):
        """Faz com que um usuário receba um e-mail com seus lembretes do dia"""

        to = conta.getEmail()
        subject = "PyMemo - Lembretes de " + self.interfacepygame.capturarData()[3] + ", " + self.interfacepygame.capturarData()[0] + " de " + self.interfacepygame.capturarData()[1] + " de " + self.interfacepygame.capturarData()[2]

        text = ""
        for lembrete in conta.listalembretes:
            if lembrete.getData() == str(datetime.now())[8:10] + str(datetime.now())[5:7]:
                text = text + (lembrete.getHora() + " " + lembrete.getTexto() + "\n")

        gmail_user = "pythonmemo@gmail.com"
        gmail_pwd = "pymemoclient"

        msg = MIMEMultipart()

        msg['From'] = gmail_user
        msg['To'] = to
        msg['Subject'] = subject

        msg.attach(MIMEText(text))

        mailServer = SMTP(self.configurarSMTP(conta.getEmail())[0], self.configurarSMTP(conta.getEmail())[1])
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(gmail_user, gmail_pwd)
        mailServer.sendmail(gmail_user, to, msg.as_string())
        mailServer.close()

    def configurarSMTP(self, emaildestino):
        """Configura o servidor SMTP dependendo do serviço de e-mail usado pelo destinatário"""

        if "gmail" in emaildestino:
            return "smtp.gmail.com", 587
        elif "hotmail" in emaildestino:
            return "smtp.live.com", 25
        elif "yahoo" in emaildestino or "ymail" in emaildestino or "rocketmail" in emaildestino:
            return "smtp.mail.yahoo.com.br", 25
        elif "bol" in emaildestino:
            return "smtp.bol.com.br", 25
        elif "uol" in emaildestino:
            return "smtp.uol.com.br", 25
        elif "terra" in emaildestino:
            return "smtp.terra.com.br", 25
        elif "ig" in emaildestino:
            return "smtp.ig.com.br", 465
        elif "ibest" in emaildestino:
            return "smtp.ibest.com.br", 465
        elif "itelefonica" in emaildestino:
            return "smtp.itelefonica.com.br", 25


def main():
    main = Main()
    main.painelContas()

if __name__ == '__main__':
    main()
